package com.yuyu.qingmangmall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.yuyu.common.constant.CartConstant;
import com.yuyu.common.utils.R;
import com.yuyu.qingmangmall.cart.feign.ProductFeignServer;
import com.yuyu.qingmangmall.cart.interceptor.CartInterceptor;
import com.yuyu.qingmangmall.cart.service.CartService;
import com.yuyu.qingmangmall.cart.to.UserInfoTo;
import com.yuyu.qingmangmall.cart.vo.Cart;
import com.yuyu.qingmangmall.cart.vo.CartItem;
import com.yuyu.qingmangmall.cart.vo.PricesVo;
import com.yuyu.qingmangmall.cart.vo.SkuInfoVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ProductFeignServer productFeignServer;

    @Autowired
    ThreadPoolExecutor executor;

    @Override
    public CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {

        BoundHashOperations<String, Object, Object> cartOps = getCartOps();

        String res = (String) cartOps.get(skuId.toString());

        CartItem cartItem= addCartItem(skuId, num);

        if (!StringUtils.isEmpty(res)){
            // 有该购物项 ，增加指定购物项的数量
            // 新增的数量
            Integer count = cartItem.getCount();
            CartItem cartItem1 = JSON.parseObject(res, CartItem.class);
            // 原有的数量
            Integer count1 = cartItem1.getCount();
            // 总数量
            cartItem.setCount(count+count1);

        }
        // 没有该购物项 ，创建该购物项

        String cartString = JSON.toJSONString(cartItem);
        cartOps.put(skuId+"",cartString); // 数据写入redis




        return cartItem;
    }


    /**
     * 拿到购物项
     * @param skuId
     * @return
     */
    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String res = (String) cartOps.get(skuId.toString());

        return JSON.parseObject(res, CartItem.class);
    }

    @Override
    public Cart getCart(UserInfoTo userInfoTo) {
        // UserInfoTo(userId=null, userKey=00ed74d7-7f20-430f-8ef5-39a4dc1a2ec0, tempUser=true)
        Cart cart = new Cart();
        if (userInfoTo.getUserId()==null){
            // 未登录
            // 临时用户购物车数据
            String cartKey= CartConstant.CART_USER_CACHE_PREFIX + userInfoTo.getUserKey();
            List<CartItem> cartItemList = getCartItems(cartKey);
            cart.setItems(cartItemList);

        }else {
            // 登陆状态  如果之前有临时用户需要将临时用户的购物车数据存入用户购物车
            List<CartItem> temporaryCartItems = null;
            if (userInfoTo.getUserKey()!=null){
                // 拿到临时用户购物车数据
                String temporaryCartKey= CartConstant.CART_USER_CACHE_PREFIX + userInfoTo.getUserKey();
                temporaryCartItems = getCartItems(temporaryCartKey);
                // 将临时用户数据放入 登录用户的数据库中
                BoundHashOperations<String, Object, Object> ops = redisTemplate.boundHashOps(CartConstant.CART_USER_CACHE_PREFIX + userInfoTo.getUserId());
                if (temporaryCartItems!=null && temporaryCartItems.size()>0){
                    for (CartItem userCartItem : temporaryCartItems) {
                        String userCartItemString = JSON.toJSONString(userCartItem);
                        ops.put(userCartItem.getSkuId()+"",userCartItemString);
                    }
                }
                // 放入后删除临时用户
                redisTemplate.delete(temporaryCartKey);
            }
            // 拿到登录用户购物车数据
            String cartKey= CartConstant.CART_USER_CACHE_PREFIX + userInfoTo.getUserId();
            List<CartItem> userCartItems = getCartItems(cartKey);

//            if (temporaryCartItems!=null&&temporaryCartItems.size()>0&&userCartItems!=null){
//                boolean b = userCartItems.addAll(temporaryCartItems);
//                System.out.println(b);
//            }
//            if (userCartItems==null||userCartItems.size()<1){
//                userCartItems=temporaryCartItems;
//            }
            cart.setItems(userCartItems);


        }



        return cart;
    }

    @Override
    public List<CartItem> getCurrentUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        if (userInfoTo.getUserId()==null){
            // 未登录
            return null;
        }else {
            // 从购物项中取出被选中的购物项
            String cartKey= CartConstant.CART_USER_CACHE_PREFIX + userInfoTo.getUserId();
            List<CartItem> cartItems = getCartItems(cartKey); // 所有购物项
            // 过滤出被选中的购物项
            List<CartItem> checkItems = cartItems.stream().filter(CartItem::getCheck).collect(Collectors.toList());
            // 拿到选中项的商品id集合
            List<Long> skuIds = checkItems.stream().map(CartItem::getSkuId).collect(Collectors.toList());
            Long[] skuIdsLong = (Long[]) skuIds.toArray(new Long[skuIds.size()]);

            // 远程商品服务查找最新的商品价格
            if (skuIdsLong.length > 0){
                List<PricesVo> newPrices = productFeignServer.getNewPrices(skuIdsLong);

                // 根据商品Id将最新价格写入购物项中
                for (CartItem cartItem : checkItems) {
                    for (PricesVo newPrice : newPrices) {
                        if (newPrice.getSkuId().equals(cartItem.getSkuId())){
                            cartItem.setPrice(newPrice.getPrice());
                            break;
                        }
                    }
                }

            }

            return checkItems;
        }

    }

    /**
     * 在redis 中取出相应的数据
     * @param cartKey
     * @return
     */
    private List<CartItem> getCartItems(String cartKey) {

        BoundHashOperations<String, Object, Object> userKeyOps = redisTemplate.boundHashOps(cartKey);
        List<Object> values = userKeyOps.values(); // .values() 可以拿到所有的数据
        List<CartItem> cartItemList = null;
        if (values!=null && values.size()>0){
            cartItemList = values.stream().map(value -> {
                String str = (String) value;
                CartItem cartItem = JSON.parseObject(str, CartItem.class);

                return cartItem;
            }).collect(Collectors.toList());

        }
        return cartItemList;
    }

    private BoundHashOperations<String, Object, Object> getCartOps() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        // 判断用户是否登录
        Long userId = userInfoTo.getUserId();
        // 购物车存储在redis的数据结构为 hash（map）k:hash  k((临时)用户Id)   hash(k(skuId):Cart)
        BoundHashOperations<String, Object, Object> cartOps;
        if (userId==null){
            // userId为空，没有登录 ,创建临时用户购物车 k=qingmang:cart:id
            cartOps = redisTemplate.boundHashOps(CartConstant.CART_USER_CACHE_PREFIX+userInfoTo.getUserKey());
        }else {
            // 创建登录用户的购物车
            cartOps = redisTemplate.boundHashOps(CartConstant.CART_USER_CACHE_PREFIX+userInfoTo.getUserId());
        }
        return cartOps;
    }


    /**
     * 新增购物项
     * @param skuId
     * @param num
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    private CartItem addCartItem(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        CartItem cartItem = new CartItem();

        // 异步编排
        // 调用远程方法 通过skuId查找相应的sku属性
        CompletableFuture<Void> skuInfo1 = CompletableFuture.runAsync(() -> {
            R r = productFeignServer.SkuInfo(skuId); // skuInfo
            SkuInfoVo skuInfo = r.getData("skuInfo", new TypeReference<SkuInfoVo>() {
            });

            cartItem.setCheck(true);
            cartItem.setCount(num);
            cartItem.setImage(skuInfo.getSkuDefaultImg());
            cartItem.setPrice(skuInfo.getPrice());
            cartItem.setSkuId(skuId);
            cartItem.setTitle(skuInfo.getSkuTitle());

        }, executor);

        // 调用远程方法 通过skuId查找相应的属性值// 调用远程方法 通过skuId查找相应的属性值
        CompletableFuture<Void> skuAttrs1 = CompletableFuture.runAsync(() -> {
            R r1 = productFeignServer.skuAttr(skuId);
            List<String> skuAttrs = r1.getData("skuAttrs", new TypeReference<List<String>>() {
            });
            List<String> newSkuAttrs = new ArrayList<>();
            if (skuAttrs != null && skuAttrs.size() > 0) {
                for (String skuAttr : skuAttrs) {
                    String[] split = skuAttr.split(":"); // 颜色:翡冷翠
                    newSkuAttrs.add(split[1]);
                }
            }
            cartItem.setSkuAttr(newSkuAttrs);
        }, executor);

        // 所有任务都要执行
        CompletableFuture.allOf(skuAttrs1,skuInfo1).get();

        return cartItem;
    }
}
